package com.cc.pms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cc.pms.service.*;
import com.cc.common.core.domain.R;
import com.cc.common.core.page.PageQuery;
import com.cc.common.core.page.PageVo;
import com.cc.common.utils.DateUtils;
import com.cc.common.utils.SecurityUtils;
import com.cc.pms.domain.Team;
import com.cc.pms.domain.TeamMember;
import com.cc.pms.domain.UserTag;
import com.cc.pms.domain.vo.TeamVo;
import com.cc.pms.mapper.TeamMapper;
import com.cc.pms.service.*;
import com.cc.pms.util.InviteCodeEncoderUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 队伍表 服务实现类
 * </p>
 *
 * @author corleone
 * @since 2025-04-19
 */
@Slf4j
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team> implements ITeamService {


    @Resource
    private ITeamMemberService iTeamMemberService;

    @Resource
    private ITeamTagService iTeamTagService;

    @Resource
    private IUserTagService userTagService;

    @Resource
    private ITeamApplicationService iTeamApplicationService;


    private ScheduledExecutorService executor;


    @Override
    public void init() {
        initExecutor();
        checkExpireTeam();
    }

    private void initExecutor() {
        this.executor = Executors.newScheduledThreadPool(1);
        this.executor.scheduleAtFixedRate(this::checkExpireTeam, 60, 90, TimeUnit.MINUTES);
    }


    private void checkExpireTeam() {
        LambdaQueryWrapper<Team> lqw = Wrappers.lambdaQuery();
        lqw.le(Team::getExpireTime, DateUtils.getTime());
        lqw.isNotNull(Team::getExpireTime);
        List<Team> teams = list(lqw);
        if (teams != null && !teams.isEmpty()) {
            for (Team team : teams) {
                removeByTeamId(team.getId());
                log.info("删除过期队伍, id: {} , team name: {} , expire_time: {}", team.getId(), team.getName(), team.getExpireTime());
            }
        }
//        select * from team where expire_time < '2025-12-12 23:23:23' and expire_time is not null
    }


    @Override
    public PageVo<TeamVo> queryTeamVoPage(PageQuery query, Team team, String beginTime, String endTime) {
        Page<TeamVo> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<TeamVo> teamVoPage = baseMapper.queryTeamVoPage(page, team , beginTime, endTime);
        return PageVo.of(teamVoPage.getRecords(), teamVoPage.getTotal());
    }

    @Override
    public PageVo<TeamVo> queryMineManageTeamVoPage(PageQuery query, Team team) {
        Page<TeamVo> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<TeamVo> teamVoPage = baseMapper.queryMineManageTeamVoPage(page, SecurityUtils.getUserId()  ,team);
        return PageVo.of(teamVoPage.getRecords(), teamVoPage.getTotal());
    }

    @Override
    public PageVo<TeamVo> queryTeamVoByTagIds(PageQuery query, List<Long> tagIds) {
        // 若前端未传 tagIds，使用用户自身绑定的标签
        if (tagIds == null || tagIds.isEmpty()) {
            List<UserTag> userTagList = userTagService.queryTagByUserId(SecurityUtils.getUserId());
            tagIds = userTagList.stream().map(UserTag::getTagId).collect(Collectors.toList());
            // 若用户未绑定任何标签，则返回空结果
            if (tagIds.isEmpty()) {
                return PageVo.of(Collections.emptyList(), 0L);
            }
        }
        Page<TeamVo> teamVoPage = baseMapper.queryTeamVoPageByTagId(new Page<>(query.getPageNum(), query.getPageSize()), SecurityUtils.getUserId(), tagIds);
        return PageVo.of(teamVoPage.getRecords(), teamVoPage.getTotal());
    }


    @Override
    public PageVo<TeamVo> queryTeamVoByName(PageQuery query, String teamName) {
        Page<TeamVo> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<TeamVo> teamVoPage = baseMapper.queryTeamVoPageByName(page, teamName, SecurityUtils.getUserId());
        return PageVo.of(teamVoPage.getRecords(), teamVoPage.getTotal());
    }

    @Override
    public TeamVo queryTeamVoByInviteCode(String inviteCode) {
        if (inviteCode == null || inviteCode.trim().isEmpty()) {
            return null;
        }
        return baseMapper.queryTeamByInviteCodeWithApplicationStatus(inviteCode, SecurityUtils.getUserId());
    }

    @Override
    public R<Long> create(Team team) {
        if (team == null || team.getName() == null || team.getType() == null || team.getMaxMembers() == null) {
            return R.fail(-1, "请求数据不能为空");
        }
        if (team.getType() == 2 && (team.getPassword() == null || team.getPassword().trim().length() < 8)) {
            return R.fail(-1, "密码输入错误,要求至少8位");
        }

        if (queryManageTeamCount(SecurityUtils.getUserId()) >= 5) {
            return R.fail(-1, "管理的队伍最大数: 5");
        }

        team.setFounderId(SecurityUtils.getUserId());
        team.setCreateTime(DateUtils.getTime());
        team.setCurrentMembers(1);
        boolean succ = save(team);
        if (succ) {
            String inviteCode = InviteCodeEncoderUtil.generateRandomString(new SecureRandom().nextInt(3) + 10);
            team.setInviteCode(inviteCode);
            updateById(team);
            TeamMember member = new TeamMember();
            member.setTeamId(team.getId());
            member.setJoinTime(DateUtils.getTime());
            member.setUserId(SecurityUtils.getUserId());
            member.setIsCaptain(1);
            iTeamMemberService.save(member);
        }
        return R.ok(team.getId());
    }


    private int queryManageTeamCount(Long userId) {
        return iTeamMemberService.queryManageTeamCount(userId);
    }

    @Override
    public R<Boolean> disbandTeam(Long teamId) {
        removeById(teamId);
        iTeamMemberService.removeByTeamId(teamId);
        iTeamTagService.removeByTeamId(teamId);
        iTeamApplicationService.removeByTeamId(teamId);
        return R.ok();
    }

    @Override
    public R<Boolean> updateTeam(Team team) {
        if (team == null) {
            return R.fail(-1, "队伍请求数据不能为空");
        }
        if (team.getType() == 2 && (team.getPassword() == null || team.getPassword().trim().length() < 8)) {
            return R.fail(-1, "密码设置错误,密码至少8位");
        }
        Team t = getById(team.getId());

        if (t.getCurrentMembers() > team.getMaxMembers()) {
            return R.fail(-1, "当前队伍人数超过设置的最大人数");
        }

        // 队伍性质改变, 公开 -> 加密/私有  删除队伍申请
        if (t.getType() == 1 && !t.getType().equals(team.getType())) {
            iTeamApplicationService.removeApplying(team.getId());
        }
        team.setUpdateBy(DateUtils.getTime());
        return R.ok(updateById(team));
    }

    @Override
    public void updateTeamMembersCount(Long teamId, Integer currentMembers) {
        lambdaUpdate().eq(Team::getId, teamId).set(Team::getCurrentMembers, currentMembers).update();
    }

    @Override
    public void removeByTeamId(Long teamId) {
        disbandTeam(teamId);
    }

    @Override
    public R<Long> joinEncryptionTeam(Team team) {
        if (team == null) {
            return R.fail(-1, "加入队伍数据不能为空");
        }
        if (team.getPassword() == null) {
            return R.fail(-1, "加入加密队伍,请填写密码");
        }
        Team t = getById(team.getId());
        if (t == null) {
            return R.fail(-1, "加入的队伍不存在");
        }
        if (t.getMaxMembers() <= t.getCurrentMembers()) {
            return R.fail(-1, "队伍已满,不可加入");
        }
        if (!t.getPassword().equals(team.getPassword())) {
            return R.fail(-1, "加入加密队伍,请输入正确密码");
        }
        TeamMember member = new TeamMember();
        member.setTeamId(team.getId());
        member.setJoinTime(DateUtils.getTime());
        member.setIsCaptain(0);
        member.setUserId(SecurityUtils.getUserId());
        return iTeamMemberService.joinTeam(member);
    }

    @Override
    public R<Long> joinPrivateTeam(Long teamId) {
        if (teamId == null) {
            return R.fail(-1, "加入队伍失败, 请求数据不能为空");
        }
        Team team = getById(teamId);
        if (team == null) {
            return R.fail(-1, "加入的队伍不存在");
        }
        if (Objects.equals(team.getMaxMembers(), team.getCurrentMembers())) {
            return R.fail(-1, "队伍已满,不可加入");
        }
        TeamMember member = new TeamMember();
        member.setUserId(SecurityUtils.getUserId());
        member.setJoinTime(DateUtils.getTime());
        member.setIsCaptain(0);
        member.setTeamId(teamId);
        return iTeamMemberService.joinTeam(member);
    }

    @Override
    public PageVo<TeamVo> queryJoinTeamVoPage(PageQuery query, Team team) {
        Page<TeamVo> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<TeamVo> teamVoPage = baseMapper.queryJoinTeamVoPage(page,SecurityUtils.getUserId(), team);
        return PageVo.of(teamVoPage.getRecords(), teamVoPage.getTotal());
    }

    @Override
    public R<Long> joinTeamByInviteCode(Team team) {
        if (team == null) {
            return R.fail(-1, "加入队伍失败, 请求数据不能为空");
        }
        team = queryTeamByInviteCode(team.getInviteCode());
        if (team == null) {
            return R.fail(-1, "加入的队伍不存在");
        }
        if (Objects.equals(team.getMaxMembers(), team.getCurrentMembers())) {
            return R.fail(-1, "队伍已满,不可加入");
        }
        TeamMember member = new TeamMember();
        member.setUserId(SecurityUtils.getUserId());
        member.setJoinTime(DateUtils.getTime());
        member.setIsCaptain(0);
        member.setTeamId(team.getId());
        return iTeamMemberService.joinTeam(member);
    }

    private Team queryTeamByInviteCode(String inviteCode) {
        LambdaQueryWrapper<Team> lqw = Wrappers.lambdaQuery();
        lqw.eq(Team::getInviteCode, inviteCode);
        lqw.last("limit 1");
        return getOne(lqw);
    }


}
